package com.settlement.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.settlement.system.common.base.IBaseEnum;
import com.settlement.system.common.enums.CancellationStatusEnum;
import com.settlement.system.common.enums.OMSOrderTypeEnum;
import com.settlement.system.common.model.Option;
import com.settlement.system.common.util.SecurityUtils;
import com.settlement.system.mapper.*;
import com.settlement.system.model.entity.*;
import com.settlement.system.model.query.AuditPageQuery;
import com.settlement.system.model.query.BillPageQuery;
import com.settlement.system.model.vo.AuditVo;
import com.settlement.system.model.vo.RoleVO;
import com.settlement.system.model.vo.SysBillVO;
import com.settlement.system.model.vo.SysOrderDetailVo;
import com.settlement.system.service.*;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * <p>
 * 个人已办或归档核销表 服务实现类
 * </p>
 *
 * @author huangrensen
 * @since 2023-08-30
 */
@Service
@RequiredArgsConstructor
public class SysDoneAuditServiceImpl extends ServiceImpl<SysDoneAuditMapper, SysDoneAudit> implements SysDoneAuditService {

    private final SysCompanyService sysCompanyService;

    private final SysDictService sysDictService;

    private final SysDoneAuditNoLinkMapper doneAuditNoLinkMapper;

    private final SysBillMapper sysBillMapper;

    private final SysPlatformService sysPlatformService;

    private final SysStoreService storeService;

    private final SysOrderDetailMapper orderDetailMapper;

    private final SysRoleService sysRoleService;


    private final SysSubjectsService sysSubjectsService;

    private final BsOmsOrderMapper bsOmsOrderMapper;

    @Override
    public Page<SysDoneAudit> getPage(AuditPageQuery queryParams) {
        // 查询参数
        int pageNum = queryParams.getPageNum();
        int pageSize = queryParams.getPageSize();
        String keywords = queryParams.getKeywords();
        LocalDateTime startDate = null;
        LocalDateTime endDate = null;
        if (queryParams.getStartDate() != null && queryParams.getEndDate() != null) {
            startDate = queryParams.getStartDate().atStartOfDay();
            endDate = queryParams.getEndDate().plusDays(1).atStartOfDay();
        }
        // 查询数据
        Page<SysDoneAudit> auditPage = this.page(
                new Page<>(pageNum, pageSize),
                new LambdaQueryWrapper<SysDoneAudit>()
                        .likeRight(StrUtil.isNotBlank(keywords), SysDoneAudit::getOrderNo, keywords)
                        .eq(SysDoneAudit::getStatus, queryParams.getStatus())
                        .eq(SysDoneAudit::getCreateBy, SecurityUtils.getUserId())
                        .eq(queryParams.getOwnerLoss() != null, SysDoneAudit::getOwnerLoss, queryParams.getOwnerLoss())
                        .eq(StrUtil.isNotBlank(queryParams.getSecordSourceCode()), SysDoneAudit::getSecordSourceCode
                                , queryParams.getSecordSourceCode())
                        .eq(StrUtil.isNotBlank(queryParams.getThirdSourceCode()), SysDoneAudit::getThirdSourceCode, queryParams.getThirdSourceCode())
                        .eq(StrUtil.isNotBlank(queryParams.getShopCode()), SysDoneAudit::getShopCode, queryParams.getShopCode())
                        .eq(StrUtil.isNotBlank(queryParams.getBillSysStore()), SysDoneAudit::getBillSysStore, queryParams.getBillSysStore())
                        .eq(StrUtil.isNotBlank(queryParams.getInnerShopCode()), SysDoneAudit::getInnerShopCode, queryParams.getInnerShopCode())
                        .eq(queryParams.getReceiveCompany() != null, SysDoneAudit::getReceiveCompany,
                                queryParams.getReceiveCompany())
                        .eq(StrUtil.isNotBlank(queryParams.getAuditStatus()), SysDoneAudit::getAuditStatus,
                                queryParams.getAuditStatus())
                        .eq(StrUtil.isNotBlank(queryParams.getPush()), SysDoneAudit::getPush,
                                queryParams.getPush())
                        .likeRight(StrUtil.isNotBlank(queryParams.getLinkNo()), SysDoneAudit::getLinkNo,
                                queryParams.getLinkNo())
                        .likeRight(StrUtil.isNotBlank(queryParams.getPoNo()), SysDoneAudit::getPoNo,
                                queryParams.getPoNo())
                        .between(startDate != null, SysDoneAudit::getBusinessDate, startDate, endDate)
                        .orderByDesc(SysDoneAudit::getBusinessDate));
        // 是否核销
        List<Option> options = sysDictService.listDictOptions("hasAudit");
        for (SysDoneAudit record : auditPage.getRecords()) {
            options.stream().filter(option -> option.getValue().equals(record.getAudit()))
                    .findFirst()
                    .ifPresent(option -> record.setAudit(option.getLabel()));
        }
        // 核销结果分类
        options = sysDictService.listDictOptions("jgfl");
        for (SysDoneAudit record : auditPage.getRecords()) {
            options.stream().filter(option -> option.getValue().equals(record.getMainTypeName()))
                    .findFirst()
                    .ifPresent(option -> record.setMainTypeName(option.getLabel()));
        }
        List<SysCompany> sysCompanyList = sysCompanyService.list();
        for (SysDoneAudit record : auditPage.getRecords()) {
            sysCompanyList.stream().filter(sysCompany -> sysCompany.getCode().equals(record.getReceiveCompany()))
                    .findFirst()
                    .ifPresent(sysCompany -> record.setReceiveCompany(sysCompany.getName()));
        }
        return auditPage;
    }

    @Override
    public AuditVo getAuditForm(String auditId) {
        SysDoneAudit sysAudit = this.getById(auditId);
        AuditVo auditVo = new AuditVo();
        BeanUtil.copyProperties(sysAudit, auditVo);
        List<RoleVO> roleList = sysRoleService.listAll();
        if (StringUtils.hasText(sysAudit.getReceiveCompany())) {
            SysCompany company = sysCompanyService.getCompanyByCode(sysAudit.getReceiveCompany());
            if (company != null) {
                auditVo.setReceiveCompanyName(company.getName());
            }
        }
        if (CancellationStatusEnum.NO.getValue().equals(sysAudit.getAuditStatus())) {
            auditVo.setAuditStatus(CancellationStatusEnum.NO.getLabel());
        } else {
            auditVo.setAuditStatus(CancellationStatusEnum.YES.getLabel());
        }
        List<Option> options = sysDictService.listDictOptions("jgfl");
        for (Option option : options) {
            if (option.getValue().equals(sysAudit.getMainTypeName())) {
                auditVo.setMainTypeName(option.getLabel());
                break;
            }
        }
        // 核销状态
        auditVo.setAuditStatus(null);
        roleList.stream().filter(option -> option.getCode().equals(sysAudit.getBelongRole()))
                .findFirst()
                .ifPresent(option -> auditVo.setAuditStatus("待%s处理".formatted(option.getName())));
        return auditVo;
    }

    @Override
    public int deleteByMonth(String billMonth) {
        return this.baseMapper.deleteByMonth(billMonth);
    }

    @Override
    public List<SysOrderDetailVo> getOrderDetailList(String doneId) {
        // 先查出归档核销单对应的待核销单列表
        List<SysDoneAuditNoLink> doneAuditNoLinks = doneAuditNoLinkMapper.selectList(new LambdaQueryWrapper<SysDoneAuditNoLink>().eq(SysDoneAuditNoLink::getDoneId, doneId));
        List<String> billMonthList = new ArrayList<>();
        String billMonth;
        for (SysDoneAuditNoLink doneAuditNoLink : doneAuditNoLinks) {
            billMonth = doneAuditNoLink.getAuditId().substring(0, 6);
            if(!billMonthList.contains(billMonth)){
                billMonthList.add(billMonth);
            }
        }
        List<SysOrderDetail> orderDetailList = new ArrayList<>();
        List<SysOrderDetailVo> orderDetailVoList = new ArrayList<>();
        if(billMonthList.size() == 0){
            return orderDetailVoList;
        }
        String tableName;
        // 根据订单ID查询订单详情
        SysOrderDetail query;
        List<SysOrderDetail> sysOrderDetails;
        for (String bMonth : billMonthList) {
            tableName = "sys_order_detail_%s".formatted(bMonth);
            query = new SysOrderDetail();
            query.setTableName(tableName);
            query.setAuditIdList(doneAuditNoLinks.stream().map(SysDoneAuditNoLink::getAuditId).toList());
            sysOrderDetails = orderDetailMapper.getList(query);
            if(sysOrderDetails.size() > 0){
                orderDetailList.addAll(sysOrderDetails);
            }
        }
        List<String> idList = orderDetailList.stream().map(SysOrderDetail::getLinkId).distinct().toList();
        List<BsOmsOrderDetail> allDetailList = new ArrayList<>();
        BsOmsOrderDetail detailQuery;
        for (String bMonth : billMonthList) {
            detailQuery = new BsOmsOrderDetail();
            detailQuery.setTableName("bs_oms_order_detail_%s".formatted(bMonth));
            detailQuery.setOIdList(idList);
            List<BsOmsOrderDetail> list = bsOmsOrderMapper.getDetailList(detailQuery);
            if(list.size() > 0){
                allDetailList.addAll(list);
            }
        }
        SysStore sysStore;
        BsOmsOrderDetail vo;
        SysOrderDetailVo detailVo;
        for (SysOrderDetail orderDetail : orderDetailList) {
            // 填充店铺
            sysStore = storeService.getById(orderDetail.getStoreId());
            if (Objects.nonNull(sysStore)) {
                orderDetail.setStoreName(sysStore.getCommercePlatformStoreName());
            }
            if (Objects.nonNull(orderDetail.getOrderType())) {
                orderDetail.setOrderTypeName(IBaseEnum.getLabelByValue(orderDetail.getOrderType(), OMSOrderTypeEnum.class));
            }
            detailVo = new SysOrderDetailVo();
            BeanUtils.copyProperties(orderDetail, detailVo);
            vo = allDetailList.stream().filter(detail -> Objects.equals(detail.getOId(), orderDetail.getLinkId())).findFirst().orElse(null);
            if(Objects.nonNull(vo)){
                BeanUtils.copyProperties(vo, detailVo, "id");
            }
            orderDetailVoList.add(detailVo);
        }
        return orderDetailVoList;
    }

    @Override
    public List<SysBillVO> getBillDetail(String doneId) {
        List<SysBillVO> allBillVOS = new ArrayList<>();
        // 先查出归档核销单对应的待核销单列表
        List<SysDoneAuditNoLink> doneAuditNoLinks = doneAuditNoLinkMapper.selectList(new LambdaQueryWrapper<SysDoneAuditNoLink>().eq(SysDoneAuditNoLink::getDoneId, doneId));
        List<String> billMonthList = new ArrayList<>();
        String billMonth;
        for (SysDoneAuditNoLink doneAuditNoLink : doneAuditNoLinks) {
            billMonth = doneAuditNoLink.getAuditId().substring(0, 6);
            if(!billMonthList.contains(billMonth)){
                billMonthList.add(billMonth);
            }
        }
        if(billMonthList.size() == 0){
            return allBillVOS;
        }
        List<SysPlatform> platformList = sysPlatformService.list();
        List<SysCompany> sysCompanyList = sysCompanyService.list();
        // 账单月份
        String tableName;
        List<SysBill> sysBillList;
        List<SysBill> sysBills = new ArrayList<>();
        BillPageQuery queryParams;
        for (String bMonth : billMonthList) {
            tableName = "sys_bill_%s".formatted(bMonth);
            queryParams = new BillPageQuery();
            queryParams.setTableName(tableName);
            queryParams.setAuditIdList(doneAuditNoLinks.stream().map(SysDoneAuditNoLink::getAuditId).toList());
            sysBillList = sysBillMapper.getList(queryParams);
            if(sysBillList.size() > 0){
                sysBills.addAll(sysBillList);
            }
        }
        SysBillVO vo;
        List<String> codes = new ArrayList<>();
        for (SysBill record : sysBills) {
            if (!codes.contains(record.getLastCode())) {
                codes.add(record.getLastCode());
            }
            if (!codes.contains(record.getOtherLastCode())) {
                codes.add(record.getOtherLastCode());
            }
            vo = new SysBillVO();
            BeanUtil.copyProperties(record, vo, "accessory", "otherAccessory");
            if (Objects.isNull(vo.getBillAmount())) {
                vo.setBillAmount(BigDecimal.ZERO);
            }
            if (org.springframework.util.StringUtils.hasText(record.getAccessory())) {
                vo.setAccessory(JSONObject.parseObject(record.getAccessory(), Map.class));
            }
            if (org.springframework.util.StringUtils.hasText(record.getOtherAccessory())) {
                vo.setOtherAccessory(JSONObject.parseObject(record.getOtherAccessory(), Map.class));
            }
            allBillVOS.add(vo);
        }
        List<SysSubjects> sysSubjectsList;
        if (codes.size() == 0) {
            sysSubjectsList = new ArrayList<>();
        } else {
            sysSubjectsList = sysSubjectsService.list(new LambdaQueryWrapper<SysSubjects>().in(SysSubjects::getLastCode, codes));
        }
        for (SysBillVO recordVo : allBillVOS) {
            sysSubjectsList.stream().filter(sysSubjects -> sysSubjects.getLastCode().equals(recordVo.getLastCode()))
                    .findFirst()
                    .ifPresent(sysSubjects -> {
                        recordVo.setLastName(sysSubjects.getLastName());
                        recordVo.setFirstCode(sysSubjects.getFirstCode());
                        recordVo.setFirstName(sysSubjects.getFirstName());
                        recordVo.setBorrowing(sysSubjects.getBorrowing());
                    });
            sysSubjectsList.stream().filter(sysSubjects -> sysSubjects.getLastCode().equals(recordVo.getOtherLastCode()))
                    .findFirst()
                    .ifPresent(sysSubjects -> {
                        recordVo.setOtherLastName(sysSubjects.getLastName());
                        recordVo.setOtherFirstCode(sysSubjects.getFirstCode());
                        recordVo.setOtherFirstName(sysSubjects.getFirstName());
                        recordVo.setOtherBorrowing(sysSubjects.getBorrowing());
                    });
            // 对方账单金额
            recordVo.setOtherBillAmount(recordVo.getBillAmount());
            // 对账系统平台名称
            platformList.stream().filter(platform -> platform.getReconciliationSystemCode().equals(recordVo.getBillSystemPlatformCode()))
                    .findFirst()
                    .ifPresent(platform -> {
                        recordVo.setBillSystemPlatformName(platform.getReconciliationSystemName());
                    });
            // 入账主体
            sysCompanyList.stream().filter(sysCompany -> sysCompany.getCode().equals(recordVo.getCompanyCode()))
                    .findFirst()
                    .ifPresent(sysCompany -> recordVo.setCompanyCode(sysCompany.getName()));
        }
        // 金额从大到小排序
        allBillVOS.sort((o1, o2) -> o2.getBillAmount().compareTo(o1.getBillAmount()));
        return allBillVOS;
    }
}
